package fr.poy.mygluco.server;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.BasePagingLoadResult;
import com.extjs.gxt.ui.client.data.PagingLoadConfig;
import com.extjs.gxt.ui.client.data.PagingLoadResult;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import fr.poy.mygluco.client.AppService;
import fr.poy.mygluco.model.AppException;
import fr.poy.mygluco.model.AppLogs;
import fr.poy.mygluco.model.Record;
import fr.poy.mygluco.model.UserProfile;
import fr.poy.mygluco.model.AppLog.LEVEL;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class AppServiceImpl extends RemoteServiceServlet implements AppService {

	private static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactions-optional");
	private static Logger log = Logger.getLogger(AppServiceImpl.class.getName());
	
	public static PersistenceManagerFactory getPmf() {
		return PMF;
	}
 
	public static enum SORT {
		ASC, DESC;
		@Override
		public String toString() {
			switch (this) {
			case ASC:
				return "asc";
			default:
				return "desc";
			}
		}
	}
 

	@SuppressWarnings("unchecked")
	public PagingLoadResult<Record> listRecord(PagingLoadConfig config) {
 
		PersistenceManager pm = PMF.getPersistenceManager();

		int start = config.getOffset();
		int range = config.getLimit();
		String orderBy = config.getSortInfo().getSortField() == null ? "date" : config.getSortInfo().getSortField();
		SORT orderSort = SortDir.ASC.equals(config.getSortInfo().getSortDir()) ? SORT.ASC : SORT.DESC;
		
		if("gxtTime".equals(orderBy)) orderBy = "time";
		if("date".equals(orderBy)) orderBy = "date "+orderSort+" , time";
		String ordering = orderBy + " " + orderSort;
		
		Query query = pm.newQuery(Record.class);
		query.setFilter("userEmail == :email"); 
		query.setOrdering(ordering);
		query.setRange(start, start + range);
		List<Record> l = (List<Record>) query.execute(UserServiceFactory.getUserService().getCurrentUser().getEmail());

		List<Record> ret = new ArrayList<Record>();
		for (Record record : l) {
			ret.add(record);
		}
		int s = (Integer) pm.newQuery("select count(id) from fr.poy.mygluco.model.Record").execute();

		pm.close();
		return new BasePagingLoadResult<Record>(ret, start, s);
	}


	private UserProfile getProfile(){
		PersistenceManager pm = PMF.getPersistenceManager();
		User u = UserServiceFactory.getUserService().getCurrentUser();  
		Query query = pm.newQuery(UserProfile.class);
	    query.setFilter("userEmail == :userEmail");
	    query.setUnique(true);
	    UserProfile ret = (UserProfile)query.execute(u.getEmail());
	    pm.close();
	    return ret;
	}
	
	
	public UserProfile loadProfile() { 
		PersistenceManager pm = PMF.getPersistenceManager();
		UserProfile ret = getProfile();
		User u = UserServiceFactory.getUserService().getCurrentUser();  
		if(ret==null){//new user
			ret = new UserProfile(u.getEmail(),u.getNickname()); 
			ret.setFirstuse(true);
			pm.makePersistent(ret); 
		}
		
		pm.close(); 
		
		ret.setLogoffUrl(UserServiceFactory.getUserService().createLogoutURL("/"));
		return ret; 
	}

	
	
	public AppLogs saveProfile(UserProfile o) {
		AppLogs ret = new AppLogs();
		PersistenceManager pm = PMF.getPersistenceManager(); 
		UserProfile a = pm.getObjectById(UserProfile.class, o.getId()); 
		a.setDayFormat(o.getDayFormat());
		a.setDateFormat(o.getDateFormat());
		a.setTimeFormat(o.getTimeFormat());
		a.setBgUnit(o.getBgUnit());
		a.setBgHigh(o.getBgHigh());
		a.setBgLow(o.getBgLow());
		a.setLimitHypo(o.getLimitHypo());
		a.setLastImport(o.getLastImport());
		a.setXmppPattern(o.getXmppPattern());
		pm.makePersistent(a); 
		//pm.detachCopy(a); marche pas ! pb de serialisation GWT, voir DOZER ?
 
		pm.close();
		ret.add(LEVEL.INFO, "Profil ok");
		return ret; 
	}
	
	@SuppressWarnings("unchecked")
	public List<Record> processImportFile() throws AppException {
		PersistenceManager pm = PMF.getPersistenceManager(); 
		//FIXME si timeout, utilisation du queue pour persister?
		final AppLogs logs = new AppLogs(); 
		
		String fileContents = (String)getThreadLocalRequest().getSession().getAttribute(UploadServlet.FILE_KEY);
		final List<Record> ret = ImportExport.xmlImport(fileContents, logs);
		
        if(logs.size()>0) throw new AppException(logs);
         
        
        //pour voir si doublon, on ajoute les logs de la meme periode 
        Date min=null, max=null;
        for (Record record : ret) {
			if(min==null || min.after(record.getDate())) min = record.getDate();
			if(max==null || max.before(record.getDate())) max = record.getDate();
		}
        Query query = pm.newQuery(Record.class); 
        query.setFilter("date >= :min && date <= :max && userEmail == :email"); 
        List<Record> rl = (List<Record>)query.execute(min,max,UserServiceFactory.getUserService().getCurrentUser().getEmail());
        
        ret.addAll(rl); 
        
        Collections.sort(ret, new Comparator<Record>() { 
			public int compare(Record o1, Record o2) { 
				int a = o2.getDate().compareTo(o1.getDate());
				if(a != 0) return a;
				a = o2.getTime() - o1.getTime();
				if(a != 0) 
					return a;
				return o1.getId()==null ? -1 : 1 ;
			} 
		}); 
        
//        for (Record record : ret) {
//			System.out.println( record.getId() +" "+record.getDate().toLocaleString()+"  "+record.getTime());
//		}
        
        pm.close();
        
		return ret;
	}

 
	public AppLogs persistRecords(List<Record> o) { 
		//FIXME surcharge email pour sécurité
		AppLogs ret = new AppLogs();
		PersistenceManager pm = PMF.getPersistenceManager(); 
		pm.makePersistentAll(o) ;
		pm.close();
		ret.add(LEVEL.INFO, "save OK");
		return ret; 
	}

 
	@SuppressWarnings("unchecked")
	public AppLogs removeAllRecords() {
		AppLogs ret = new AppLogs();
		PersistenceManager pm = PMF.getPersistenceManager(); 
		
		Query query = pm.newQuery(Record.class); 
        query.setFilter("userEmail == :email"); 
        query.deletePersistentAll(UserServiceFactory.getUserService().getCurrentUser().getEmail());
         
		pm.close();
		ret.add(LEVEL.INFO, "delete records OK");
		return ret; 
	}
 
 
}
